#ifndef   	UNARY_PARSER_H
#define   	UNARY_PARSER_H

#include "basic_parser.h"
#include "parser.h"

namespace eg {

using namespace std;

//==================================================================================================
//                                      Predicate parsers
//==================================================================================================

// Parser for the and predicate (&p)
class and_parser: public unary_parser {

public:

	and_parser(parser * arg) :
		unary_parser(arg) {
	}

	bool parse(bool gen_ast = true);

	string to_string() {
		return string("&(") + argument->to_string() + ')';
	}
	string parser_name() {
		return " 'and parser' ";
							}
};

// Parser for the not predicate (!p)
class not_parser: public unary_parser {

public:

	not_parser(parser * arg) :
		unary_parser(arg) {
	}

	bool parse(bool gen_ast = true);

	string to_string() {
		return string("!(") + argument->to_string() + ')';
	}
	string parser_name() {
			return " 'not parser' ";
								}

};

//==================================================================================================
//                                      postfix parsers
//==================================================================================================

// Zero or more parser (P*)
class zero_or_more_parser: public unary_parser {

public:

	zero_or_more_parser(parser * arg) :
		unary_parser(arg) {
	}

	bool parse(bool gen_ast = true);

	string to_string() {
		return string("(") + argument->to_string() + ")*";
	}
	string parser_name() {
			return " 'zero or more parser' ";
								}

};

// One or more parser (P+)
class one_or_more_parser: public unary_parser {

public:

	one_or_more_parser(parser * arg) :
		unary_parser(arg) {
	}

	bool parse(bool gen_ast = true);

	string to_string() {
		return string("(") + argument->to_string() + ")+";
	}
	string parser_name() {
			return " 'one_or_more parser' ";
								}

};

// Zero or one parser (P?)
class zero_or_one_parser: public unary_parser {

public:

	zero_or_one_parser(parser * arg) :
		unary_parser(arg) {
	}

	bool parse(bool gen_ast = true);

	string to_string() {
		return string("(") + argument->to_string() + ")?";
	}
	string parser_name() {
			return " 'maybe parser' ";
								}

};

// Class representing a grammar rule: id = expr. A grammar rule contains a parser.
class rule: public unary_parser {

public:

	rule(string name = "") :
		unary_parser(0), r_name(name) {
	}

	parser & operator=(parser & p) {
		argument = &p;
		return *this;
	}
	;

	bool parse(bool gen_ast = true);

	string to_string() {
		return r_name + " = " + argument->to_string();
	}

	bool is_a_rule() {
		return true;
	}
	parser & z_o_m(parser & p);
	string parser_name() {
		return r_name;
	}
	/*stack<parser *> get_error_parsers_stack() const {		// error parsers stack of each rule
		return error_parsers_stack;
	}*/
	//stack<parser *> error_parsers_stack;

private:

	string r_name;
	//stack<parser *> error_parsers_stack;		// error parsers stack

};

// a parser to skip blanks
class blanks: public parser {

public:
	blanks() :
		b("blanks") {
		b = one_or_more(a_char(' '));
	}
	~blanks() {
	}
	bool parse(bool gen_ast = true) {
		parser * aux_parser = the_context->disable_parser();
		bool result = b.parse();
		the_context->enable_parser(aux_parser);
		return result;
	}

private:

	rule b;

};


}

#endif
